package middleware

import (
	"github.com/gin-gonic/gin"
	"guard/internal/conf"
	"guard/internal/errors"
	"guard/internal/result"
	"guard/internal/tool"
	"net/http"
	"strings"
)

// AuthLogin 本地登录验证处理
func AuthLogin(c *gin.Context) {

	// 创建session
	sess := NewSessionCache(c.Writer, c.Request)

	// 从session中取用户
	username := sess.GetLoginState()

	//都取不到
	if username == "" || len(username) == 0 {
		// session里设置一个跳转的url记录
		sess.Session.Set(conf.Conf.Cache.GotoUri, c.Request.RequestURI)
		// 没有登录
		c.Redirect(http.StatusMovedPermanently, "/login") // 使用302重定向是临时重定向，表示请求的资源仍然存在，但是需要临时跳转到另一个URL。
		c.Abort()
		return
	}

	/**
	ID很少用到，改为只存username
	*/
	// 用户信息向下传递
	c.Set(conf.Conf.Cache.LoginUserKey, username)
	c.Next()
}

// AuthLoginJson 本地认证，返回json
func AuthLoginJson(c *gin.Context) {
	// 创建session
	sess := NewSessionCache(c.Writer, c.Request)

	// 从session中取用户
	username := sess.GetLoginState()

	if username == "" || len(username) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 401,
			"msg":  "身份验证失败，请重新登录",
			"data": nil,
		})
		c.Abort()
		return
	}

	c.Set(conf.Conf.Cache.LoginUserKey, username)
	c.Next()
}

// TokenAuth token验证
func TokenAuth(scope string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从header里取token
		tokenBearer := c.GetHeader("Authorization")

		// 如果header里没有Authorization
		if tokenBearer == "" {
			_ = c.Error(errors.OtherError("token不存在"))
			c.Abort()
			return
		}

		tokenList := strings.Split(tokenBearer, " ")

		// 只有header里token没有任何一个，都报错
		if len(tokenList) < 2 || tokenList[0] != "Bearer" {
			_ = c.Error(errors.OtherError("token参数异常"))
			c.Abort()
			return
		}

		// 解析token
		user, err := tool.ParseToken(tokenList[1])
		if err != nil || user == nil {
			_ = c.Error(err)
			c.Abort()
			return
		}

		// 一次性校验权限
		found := false
		for _, sc := range user.Scope {
			if scope == sc {
				// 如果有权限，用户名向下传递，不传权限
				c.Set(conf.Conf.Cache.LoginUserKey, user.Subject)
				c.Next()
				found = true
				break
			}
		}

		if !found {
			// 没有权限，则返回
			c.JSON(http.StatusForbidden, result.Build{
				Code: http.StatusForbidden,
				Msg:  "没有权限",
				Data: nil,
			})
			c.Abort() // 必须加这个把当前controller终止
			return
		}
	}
}
